{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# K&K Problem Generation Library\n",
    "\n",
    "**NOTE: This notebook is for demonstration purpose and the latest code is refactored into `lib_kk.py`**."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "import sys\n",
    "import importlib\n",
    "import pprint\n",
    "\n",
    "module_path = os.path.abspath('.')\n",
    "if not module_path in sys.path:\n",
    "    sys.path.append(module_path)\n",
    "import lib_kk\n",
    "importlib.reload(lib_kk)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'all_solutions': [(True, False, True, False, True)],\n",
      " 'solution': (True, False, True, False, True),\n",
      " 'statements': (('or', ('telling-truth', 3), ('telling-truth', 2)),\n",
      "                ('not', ('telling-truth', 2)),\n",
      "                ('->', ('lying', 0), ('telling-truth', 3)),\n",
      "                ('->', ('lying', 1), ('lying', 4)),\n",
      "                ('not', ('lying', 0)))}\n"
     ]
    }
   ],
   "source": [
    "n_people = 5\n",
    "problem_sampler = lib_kk.KKProblemSampler(1234, n_people=n_people)\n",
    "problems = problem_sampler.sample_valid_problems(10)\n",
    "\n",
    "pprint.pprint(problems[0])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[(False, False, False, False, False)]\n",
      "[('proposal', {'assignment': True, 'outcome': 'ok', 'person': 0}),\n",
      " ('proposal',\n",
      "  {'assignment': True,\n",
      "   'conflict_statement': (0, True),\n",
      "   'outcome': 'conflict',\n",
      "   'person': 3}),\n",
      " ('proposal',\n",
      "  {'assignment': False,\n",
      "   'conflict_statement': (3, False),\n",
      "   'outcome': 'conflict',\n",
      "   'person': 3}),\n",
      " ('reconsider', {'exhausted': [3], 'person': 0}),\n",
      " ('proposal', {'assignment': False, 'outcome': 'ok', 'person': 0}),\n",
      " ('proposal',\n",
      "  {'assignment': True,\n",
      "   'conflict_statement': (3, True),\n",
      "   'outcome': 'conflict',\n",
      "   'person': 3}),\n",
      " ('proposal', {'assignment': False, 'outcome': 'ok', 'person': 3}),\n",
      " ('proposal',\n",
      "  {'assignment': True,\n",
      "   'conflict_statement': (0, False),\n",
      "   'outcome': 'conflict',\n",
      "   'person': 4}),\n",
      " ('proposal', {'assignment': False, 'outcome': 'ok', 'person': 4}),\n",
      " ('proposal',\n",
      "  {'assignment': True,\n",
      "   'conflict_statement': (2, True),\n",
      "   'outcome': 'conflict',\n",
      "   'person': 2}),\n",
      " ('proposal', {'assignment': False, 'outcome': 'ok', 'person': 2}),\n",
      " ('proposal',\n",
      "  {'assignment': True,\n",
      "   'conflict_statement': (1, True),\n",
      "   'outcome': 'conflict',\n",
      "   'person': 1}),\n",
      " ('proposal', {'assignment': False, 'outcome': 'ok', 'person': 1}),\n",
      " ('success', {'assignments': (False, False, False, False, False)})]\n"
     ]
    }
   ],
   "source": [
    "problem = problems[2]\n",
    "\n",
    "print(lib_kk.find_solution(problem['statements']))\n",
    "chain_of_thoughts = lib_kk.generate_chain_of_thoughts(problem['statements'])\n",
    "pprint.pprint(chain_of_thoughts)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'knight_knave': {'Knave': 'Knave',\n",
      "                  'Knight': 'Knight',\n",
      "                  'a_knave': 'a knave',\n",
      "                  'a_knight': 'a knight',\n",
      "                  'knave': 'knave',\n",
      "                  'knight': 'knight'},\n",
      " 'names': ['David', 'Zoey', 'Alexander', 'Aurora', 'Isabella'],\n",
      " 'quiz': 'A very special island is inhabited only by knights and knaves. '\n",
      "         'Knights always tell the truth, and knaves always lie. You meet 5 '\n",
      "         'inhabitants: David, Zoey, Alexander, Aurora, and Isabella. In '\n",
      "         'David\\'s words: \"Aurora is a knave and Isabella is a knight\". Zoey '\n",
      "         'expressed that Aurora is a knave if and only if Isabella is a '\n",
      "         'knight. Alexander said, \"Isabella is a knight.\" Aurora commented, '\n",
      "         '\"David is a knight\". According to Isabella, \"Alexander is a knight '\n",
      "         'if and only if Alexander is a knave\". So who is a knight and who is '\n",
      "         'a knave?',\n",
      " 'solution': (False, False, False, False, False),\n",
      " 'solution_text': 'David is a knave, Zoey is a knave, Alexander is a knave, '\n",
      "                  'Aurora is a knave, and Isabella is a knave.'}\n",
      "============================================================\n",
      "A very special island is inhabited only by knights and knaves. Knights always tell the truth, and knaves always lie. You meet 5 inhabitants: David, Zoey, Alexander, Aurora, and Isabella. In David's words: \"Aurora is a knave and Isabella is a knight\". Zoey expressed that Aurora is a knave if and only if Isabella is a knight. Alexander said, \"Isabella is a knight.\" Aurora commented, \"David is a knight\". According to Isabella, \"Alexander is a knight if and only if Alexander is a knave\". So who is a knight and who is a knave?\n"
     ]
    }
   ],
   "source": [
    "formatter = lib_kk.KKProblemFormatter(1234, problem)\n",
    "formatted_problem = formatter.format_problem(random_knight_knave_pairs=False, flip_knight_knave_pair=False)\n",
    "pprint.pprint(formatted_problem)\n",
    "print('='*60)\n",
    "print(formatted_problem['quiz'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Let's think step by step, by considering whether each person is lying and if that leads to contradiction.\n",
      "\\begin{enumerate}[leftmargin=*, itemsep=0pt, topsep=0pt, partopsep=0pt]\n",
      "\\item Assume David is a knight. No contradiction is found in their claim that Aurora is a knave and Isabella is a knight.\n",
      "\\item Aurora cannot be a knight, because this would contradict the claim of David that Aurora is a knave and Isabella is a knight.\n",
      "\\item Aurora cannot be a knave, because this would contradict the false claim of their own that David is a knight.\n",
      "\\item We have exhausted all possibilities for Aurora, so let us go back and reconsider David.\n",
      "\\item Assume David is a knave. No contradiction is found in their false claim that Aurora is a knave and Isabella is a knight.\n",
      "\\item Aurora cannot be a knight, because this would contradict the claim of their own that David is a knight.\n",
      "\\item Assume Aurora is a knave. No contradiction is found in their false claim that David is a knight.\n",
      "\\item Isabella cannot be a knight, because this would contradict the false claim of David that Aurora is a knave and Isabella is a knight.\n",
      "\\item Assume Isabella is a knave. No contradiction is found in their false claim that Alexander is a knight if and only if Alexander is a knave.\n",
      "\\item Alexander cannot be a knight, because this would contradict the claim of their own that Isabella is a knight.\n",
      "\\item Assume Alexander is a knave. No contradiction is found in their false claim that Isabella is a knight.\n",
      "\\item Zoey cannot be a knight, because this would contradict the claim of their own that Aurora is a knave if and only if Isabella is a knight.\n",
      "\\item Assume Zoey is a knave. No contradiction is found in their false claim that Aurora is a knave if and only if Isabella is a knight.\n",
      "\\end{enumerate}\n",
      "This leads to a feasible solution.\n"
     ]
    }
   ],
   "source": [
    "begin, steps, end = lib_kk.format_chain_of_thoughts(problem, formatted_problem, chain_of_thoughts, \n",
    "                                                    repeat_claim_for_assumption=True, repeat_claim_for_contradiction=True)\n",
    "print(begin)\n",
    "print('\\\\begin{enumerate}[leftmargin=*, itemsep=0pt, topsep=0pt, partopsep=0pt]')\n",
    "for s in steps:\n",
    "  print(f'\\\\item {s}')\n",
    "print('\\\\end{enumerate}')\n",
    "print(end)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "kk",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.19"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
